/**
 * Copyright (c) 2016-2020 https://github.com/zhaohuatai
 *
 * contact z_huatai@qq.com
 *  
 */
package org.zfes.snowy.auth.biz.service.impl;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.zfes.snowy.auth.biz.dao.AuthUserMapper;
import org.zfes.snowy.auth.biz.model.AuthRole;
import org.zfes.snowy.auth.biz.model.AuthUser;
import org.zfes.snowy.auth.biz.service.IAuthRoleService;
import org.zfes.snowy.auth.biz.service.IAuthUserService;
import org.zfes.snowy.auth.shiro.util.ShiroMD5EndecryptUtil;
import org.zfes.snowy.core.idcenter.IDGenerator;
import org.zfes.snowy.core.data.DataSet;
import org.zfes.snowy.base.dao.params.ParamMap;
import org.zfes.snowy.core.util.ZAlert;
import org.zfes.snowy.core.util.ZAssert;
import org.zfes.snowy.core.util.ZBeanUtil;
import org.zfes.snowy.core.util.ZObjectUtil;
import org.zfes.snowy.core.util.ZStrUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;

@Service
@Lazy(true)
public class AuthUserServiceImpl implements IAuthUserService{
	
	@Autowired
	private AuthUserMapper authUserMapper;
	
	@Autowired
	private IAuthRoleService authRoleService;
	
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public Optional<AuthUser> loadAuthUser(Long id) {
		if(id!=null){
			return Optional.ofNullable(authUserMapper.selectByPrimaryKey(id));
		}
		return Optional.empty();
	}
	
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public Optional<AuthUser> loadByAccount(String username) {
		if(ZStrUtil.hasText(username)){
			return Optional.ofNullable(authUserMapper.selectByAccount(username));
		}
		return Optional.empty();
	}
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public Optional<AuthUser> loadByOpenId(String openId) {
		if(ZStrUtil.hasText(openId)){
			return Optional.ofNullable(authUserMapper.selectByOpenId(openId));
		}
		return Optional.empty();
	}
	
	@Transactional(rollbackFor=Exception.class)
	@Override
	public void updateAuthUser(AuthUser authUser) {
		ZBeanUtil.validateBean(authUser);
		authUserMapper.updateByPrimaryKeySelective(authUser);
	}
	
//	@Transactional(rollbackFor=Exception.class)
//	@Override
//	public void deleteAuthUser(Long userId) {
//		ZAssert.notNull(userId, "请选择数据");
//		authUserMapper.deleteByPrimaryKey(userId);
//		
//	}
	
	
//	@Transactional(rollbackFor=Exception.class)
//	@Override
//	public void batchDeleteAuthUser(List<Long> userIds) {
//		ZAssert.notEmpty(userIds, "请选择数据");
//		authUserMapper.batchDeleteAuthUser(userIds);
//	}
	
	@Transactional(rollbackFor=Exception.class)
	@Override
	public void setUserStatus(List<Long> userIds, Boolean enabled, Boolean accountExpired, Boolean accountLocked,Boolean credentialsExpired){
		ZAssert.notNull(userIds, "请选择数据");
		if(enabled!=null){
			authUserMapper.updateEnabled(userIds, enabled);
		}
		if(accountExpired!=null){
			authUserMapper.updateAccountExpired(userIds, accountExpired);
		}
		if(accountLocked!=null){
			authUserMapper.updateAccountLocked(userIds, accountLocked);
		}
		if(credentialsExpired!=null){
			authUserMapper.updateCredentialsExpired(userIds, credentialsExpired);
		}
	}
	
	
	@Transactional(rollbackFor=Exception.class)
	@Override
	public void setAccountExpired(List<Long> userIds, Boolean accountExpired){
		ZAssert.notNull(userIds, "请选择数据");
		ZAssert.notNull(accountExpired, "状态参数错误");
		authUserMapper.updateAccountExpired(userIds, accountExpired);
	}
	@Transactional(rollbackFor=Exception.class)
	@Override
	public void setAccountLocked(List<Long> userIds, Boolean accountLocked){
		ZAssert.notNull(userIds, "请选择数据");
		ZAssert.notNull(accountLocked, "状态参数错误");
		authUserMapper.updateAccountLocked(userIds, accountLocked);
	}
	@Transactional(rollbackFor=Exception.class)
	@Override
	public void setCredentialsExpired(List<Long> userIds, Boolean credentialsExpired){
		ZAssert.notNull(userIds, "请选择数据");
		ZAssert.notNull(credentialsExpired, "状态参数错误");
		authUserMapper.updateCredentialsExpired(userIds, credentialsExpired);
	}
	@Transactional(rollbackFor=Exception.class)
	@Override
	public void setAuthLevel(Long userId,int authLevel){
		ZAssert.notNull(userId, "请选择数据");
		//ZAssert.isTrue(Stream.of(0,1,2).allMatch(val->val==authLevel), "状态参数错误");
		authUserMapper.updateAuthLevel(userId, authLevel);
	}
//	@Transactional(rollbackFor=Exception.class)
//	@Override
//	public void setAuthUserPwd(Long userId, String password,String salt){
//		ZAssert.notNull(userId, "请选择数据");
//		ZAssert.hasText(password, "状态参数错误");
////		String salt=ShiroMD5EndecryptUtil.genRandomSalt();
////		String entryPassword=ShiroMD5EndecryptUtil.genSetp2Password(password, salt);
//		authUserMapper.updateUserPwd(userId, password,salt);
//	}
	
	
	@Transactional(rollbackFor=Exception.class)
	@Override
	public void setDefaultRole(List<Long> userIds, Long roleId){
		ZAssert.notNull(userIds, "请选择数据");
		ZAssert.notNull(roleId, "状态参数错误");
		Optional<AuthRole>  authRoleOp=authRoleService.loadAuthRole(roleId);
		ZAssert.notEmpty(authRoleOp,  "未查询到角色数据");
		ZAssert.isTrue(authRoleOp.get().getEnabled(), "该角色状态禁用");
		authUserMapper.updateDefaultRole(userIds, roleId);
	}

	
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public DataSet loadAuthUserList(Map<String, Object> params) {
		ParamMap pm=ParamMap.filterParam(params);
		pm.getStr("userName").ifPresent(v -> pm.updateParam( "userName", "%"+v+"%"));
		pm.getLong("roleId").ifPresent(v -> pm.updateParam( "roleId", v));
		pm.getLong("roleId").ifPresent(v -> pm.updateParam( "default_role", v));
		pm.getBoolean("enabled").ifPresent(v -> pm.updateParam( "enabled", v));
		pm.getStr("defaultOrg").ifPresent(v -> pm.updateParam( "default_org", v));
		DataSet ds=DataSet.newDS(authUserMapper.selectAuthUserListCount(pm), authUserMapper.selectAuthUserList(pm));
		return ds;
	}
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public Long createAccount(String account,String password,String roleCode) {
		ZAssert.hasText(account, "账号参数错误");
		ZAssert.hasText(password, "密码参数错误");
		
		String salt=ShiroMD5EndecryptUtil.genRandomSalt();
		String finalPsw=ShiroMD5EndecryptUtil.genSetp2Password(password, salt);
		
		Optional<AuthRole> authRole =authRoleService.loadAuthRoleByCode(roleCode);
		ZAssert.notEmpty(authRole, "未查询到角色数据");
		AuthUser authUser=AuthUser.newDeafultAuthUser(account, finalPsw, salt, 6L);
		authUser.setAuthLevel(2);
		authUser.setDefaultRole(authRole.get().getId());
		
		Long userId=createUser(authUser);
		return userId;
	}
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public Long createAccount(String account,String password,Long roleId) {
		ZAssert.hasText(account, "账号参数错误");
		ZAssert.hasText(password, "密码参数错误");
		
		String salt=ShiroMD5EndecryptUtil.genRandomSalt();
		String finalPsw=ShiroMD5EndecryptUtil.genSetp2Password(password, salt);
		
		Optional<AuthRole> authRole =authRoleService.loadAuthRole(roleId);
		ZAssert.notEmpty(authRole, "角色不能为空");
		AuthUser authUser=AuthUser.newDeafultAuthUser(account, finalPsw, salt, 6L);
		authUser.setAuthLevel(2);
		authUser.setDefaultRole(authRole.get().getId());
		
		Long userId=createUser(authUser);
		return userId;
	}
	@Transactional(rollbackFor=Exception.class)
	@Override
	public Long createUser(AuthUser authUser){
		ZAssert.notNull(authUser, "参数错误");
		ZAssert.hasText(authUser.getAccount(), "账户名不能为空");
		ZAssert.notNull(authUser.getDefaultRole(), "默认角色不能为空");
		ZAssert.hasText(authUser.getPassword(), "账户密码不能为空");
		//ZAssert.hasText(authUser.getSalt(), "密码salt不能为空");
		AuthUser authUser_=authUserMapper.selectByAccount(authUser.getAccount());
		if(!ZObjectUtil.isEmpty(authUser_)){
			ZAlert.Error("该用户账号已经存在");
		}
		
		Optional<AuthRole> authRole =authRoleService.loadAuthRole(authUser.getDefaultRole());
		ZAssert.notEmpty(authRole, "该角色不能为空");
		ZAssert.isTrue(authRole.get().getEnabled(), "该角色状态为禁用");
		
//		String orgTreeCode=authUser.getDefaultOrg();
//		if(ZStrUtil.hasText(orgTreeCode)){
//			Optional<SysOrganization>  orgOp=sysOrganizationService.loadOrganizationByOrgTreeCode(orgTreeCode);
//			ZAssert.notEmpty(orgOp,"未查询到该组织机构");
//			ZAssert.isTrue(orgOp.get().getEnabled(), "该组织机构状态为禁用");
//		}
//		Long positionId=authUser.getDefaultPosition();
//		if(ZObjectUtil.isEmpty(positionId)){
//			Optional<SysPosition>  posiotnOp=sysPositionService.loadSysPosition(positionId);
//			ZAssert.notEmpty(posiotnOp,"未查询到该职位");
//			ZAssert.isTrue(posiotnOp.get().getEnabled(), "该职位状态为禁用");
//		}
		if(ZObjectUtil.isEmpty(authUser.getEnabled())){
			authUser.setEnabled(true);
		}
		if(ZObjectUtil.isEmpty(authUser.getAccountExpired())){
			authUser.setAccountExpired(false);
		}
		if(ZObjectUtil.isEmpty(authUser.getAccountLocked())){
			authUser.setAccountLocked(false);
		}
		if(ZObjectUtil.isEmpty(authUser.getCredentialsExpired())){
			authUser.setCredentialsExpired(false);
		}
//		String pwd1=ShiroMD5EndecryptUtil.genSetp1Password(authUser.getPassword());
//		String salt=ShiroMD5EndecryptUtil.genRandomSalt();
//		String entryPassword=ShiroMD5EndecryptUtil.genSetp2Password(pwd1, salt);
//		authUser.setPassword(entryPassword);
//		authUser.setSalt(salt);
		authUser.setId(IDGenerator.genLongId());
		authUserMapper.insertSelective(authUser);
		return authUser.getId();
	}

	@Transactional(rollbackFor=Exception.class)
	@Override
	public void setAuthUserPwd(Long userId, String password) {
		ZAssert.notNull(userId, "用户参数错误");
		ZAssert.hasText(password, "用户新密码不能为空");
		AuthUser authUser=authUserMapper.selectByPrimaryKey(userId);
		ZAssert.notNull(authUser, "未查到用户数据");
		String salt=authUser.getSalt();
		ZAssert.hasLength(salt,"用户盐值信息错误");
		String entryPassword=ShiroMD5EndecryptUtil.genSetp2Password(password, salt);
		authUser.setPassword(entryPassword);
		authUserMapper.updateByPrimaryKeySelective(authUser);
	}

	@Transactional(rollbackFor=Exception.class)
	@Override
	public void changePwd(Long userId, String newPassword, String oldPassword) {
		ZAssert.notNull(userId, "用户参数错误");
		ZAssert.hasText(newPassword, "用户新密码不能为空");
		ZAssert.hasText(oldPassword, "用户原密码不能为空");
		AuthUser authUser=authUserMapper.selectByPrimaryKey(userId);
		ZAssert.notNull(authUser, "未查到用户数据");
		String salt=authUser.getSalt();
		ZAssert.hasLength(salt,"用户盐值信息错误");
		
		String entryPasswordCheck=ShiroMD5EndecryptUtil.genSetp2Password(oldPassword, salt);
		ZAssert.equals(entryPasswordCheck, authUser.getPassword(), "原密码错误");
		
		String entryPassword=ShiroMD5EndecryptUtil.genSetp2Password(newPassword, salt);
		authUser.setPassword(entryPassword);
		authUserMapper.updateByPrimaryKeySelective(authUser);
		
	}

	public static void main(String[] args) {

		/*String oldPassword = "admin";
		String salt = "a767ec06b36de25389055541a23f630b";
		String password = "e61aab677ca46224d22acbb493247d69";
		String pwd1=ShiroMD5EndecryptUtil.genSetp1Password(oldPassword);
		String entryPasswordCheck=ShiroMD5EndecryptUtil.genSetp2Password(pwd1, salt);
		System.out.println(entryPasswordCheck);
		System.out.println(password);
		ZAssert.equals(entryPasswordCheck, password, "原密码错误");*/

		/**/
		String password = "123456";
		String pwd1=ShiroMD5EndecryptUtil.genSetp1Password(password);
		String salt=ShiroMD5EndecryptUtil.genRandomSalt();
		String entryPassword=ShiroMD5EndecryptUtil.genSetp2Password(pwd1, salt);
		System.out.println(salt);
		System.out.println(entryPassword);

	}

}